package ru.ifmo.itmokis;

import ru.ifmo.itmokis.gui.Controller;
import javax.persistence.Persistence;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import org.apache.log4j.Logger;
import org.picocontainer.DefaultPicoContainer;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.behaviors.Caching;
import ru.ifmo.itmokis.algo.*;
import ru.ifmo.itmokis.gui.MainFrame;
import ru.ifmo.itmokis.sim.*;
import ru.ifmo.itmokis.util.*;

/**
 *
 * @author Ivan Stepuk
 */
public class Main {

    /**
     * Application entry point
     *
     * @param args
     */
    public static void main(String... args) {

        // Inversion of control
        MutablePicoContainer container = new DefaultPicoContainer(new Caching());
        container.addComponent(Clock.class);
        container.addComponent(Config.class);
        container.addComponent(Controller.class);
        container.addComponent(Facade.class);
        container.addComponent(Persistence.createEntityManagerFactory("persistence").createEntityManager());
        container.addComponent(DataContext.class);
        container.addComponent(MainFrame.class);
        container.addComponent(ProductionQueue.class);
        container.addComponent(OrderFactory.class);
        container.addComponent(Randoms.class);
        container.addComponent(Optimizer.class);
        container.addComponent(Normalizer.class);
        container.addComponent(SupplyFactory.class);
        container.addComponent(DeliveryFactory.class);
        container.addComponent(SupplyBuilder.class);
        container.addComponent(MiniServer.class);
        container.addComponent(Statistics.class);

        // Configure clock listeners
        Clock clock = container.getComponent(Clock.class);
        Controller controller = container.getComponent(Controller.class);
        SupplyFactory supplyFactory = container.getComponent(SupplyFactory.class);
        DeliveryFactory deliveryFactory = container.getComponent(DeliveryFactory.class);
        OrderFactory orderFactory = container.getComponent(OrderFactory.class);
        ProductionQueue productionQueue = container.getComponent(ProductionQueue.class);
        Statistics statistics = container.getComponent(Statistics.class);

        clock.addClockListener(controller);
        clock.addClockListener(supplyFactory);
        clock.addClockListener(deliveryFactory);
        clock.addClockListener(orderFactory);
        clock.addClockListener(productionQueue);
        clock.addClockListener(statistics);

        // Start server
        MiniServer server = container.getComponent(MiniServer.class);
        try {
            server.start();
        } catch (Exception ex) {
            Logger.getLogger(Main.class).error("Server start failed");
        }

        // Initialize GUI
        try {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
        } catch (Exception ex) {
            Logger.getLogger(Main.class).error("Laf initialization failed");
        }
        final MainFrame main = container.getComponent(MainFrame.class);
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                main.setVisible(true);
            }
        });

        // Rerort if all is OK
        Logger.getLogger(Main.class).debug("  ========  READY  ========  ");
    }
}
